package com.wzdigit.wms.wms.service.inv.count;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.wzdigit.framework.Shift;
import com.wzdigit.mes.basic.api.BasicDataItemDetailApi;
import com.wzdigit.mes.basic.api.BasicSimpleCodeRuleApi;
import com.wzdigit.mes.basic.dto.DataItemDetailDTO;
import com.wzdigit.wms.basic.client.Pager;
import com.wzdigit.wms.basic.client.PagerInfo;
import com.wzdigit.wms.basic.client.request.transfer.SearchInvRequest;
import com.wzdigit.wms.basic.client.response.Result;
import com.wzdigit.wms.basic.domain.asn.AsnDtl;
import com.wzdigit.wms.basic.domain.asn.AsnDtlGoods;
import com.wzdigit.wms.basic.domain.asn.AsnHeader;
import com.wzdigit.wms.basic.domain.dtos.inventory.UpdateInventoryInputDto;
import com.wzdigit.wms.basic.domain.inventory.Goods;
import com.wzdigit.wms.basic.domain.inventory.GoodsHis;
import com.wzdigit.wms.basic.domain.inventory.GoodsLog;
import com.wzdigit.wms.basic.domain.inventory.Lotno;
import com.wzdigit.wms.basic.domain.order.TrsnDtl;
import com.wzdigit.wms.basic.domain.order.TrsnDtlGoods;
import com.wzdigit.wms.basic.domain.order.TrsnHeader;
import com.wzdigit.wms.basic.domain.transfer.GdnDtl;
import com.wzdigit.wms.basic.domain.transfer.GdnDtlGoods;
import com.wzdigit.wms.basic.domain.transfer.GdnHeader;
import com.wzdigit.wms.basic.domain.util.ExportExcleDTO;
import com.wzdigit.wms.basic.enums.*;
import com.wzdigit.wms.basic.enums.inventory.count.approve.InvAprResultEnum;
import com.wzdigit.wms.basic.enums.inventory.count.dif.InvDifAdjResultEnum;
import com.wzdigit.wms.basic.enums.inventory.count.dif.InvDifDtlStatusEnum;
import com.wzdigit.wms.basic.enums.inventory.count.dif.InvDifGoodsStatusEnum;
import com.wzdigit.wms.basic.enums.inventory.count.dif.InvDifStatusEnum;
import com.wzdigit.wms.basic.enums.inventory.count.dtl.InvDtlResultEnum;
import com.wzdigit.wms.basic.enums.inventory.count.dtl.InvDtlStatusEnum;
import com.wzdigit.wms.basic.enums.inventory.count.dtl.InvIsReplayEnum;
import com.wzdigit.wms.basic.enums.inventory.count.dtl.InvTaskTypeEnum;
import com.wzdigit.wms.basic.enums.inventory.count.goods.InvIsExitEnum;
import com.wzdigit.wms.basic.enums.inventory.count.header.InvGranularityEnum;
import com.wzdigit.wms.basic.enums.inventory.count.header.InvHeaderResultEnum;
import com.wzdigit.wms.basic.enums.inventory.count.header.InvHeaderStatusEnum;
import com.wzdigit.wms.basic.mapper.core.inventory.*;
import com.wzdigit.wms.basic.mapper.core.order.*;
import com.wzdigit.wms.basic.mapper.core.transfer.GdnDtlGoodsMapper;
import com.wzdigit.wms.basic.mapper.core.transfer.GdnDtlMapper;
import com.wzdigit.wms.basic.mapper.core.transfer.GdnHeaderMapper;
import com.wzdigit.wms.basic.service.code.InventoryService;
import com.wzdigit.wms.basic.util.HttpSessionUtil;
import com.wzdigit.wms.common.utils.ExportExcelUtils;
import com.wzdigit.wms.wms.client.request.inv.count.CountHeaderRequest;
import com.wzdigit.wms.wms.client.request.inv.count.dto.ReDifCountDtl;
import com.wzdigit.wms.wms.client.request.inv.count.dto.ResultApprDto;
import com.wzdigit.wms.wms.client.response.inv.count.*;
import com.wzdigit.wms.wms.client.response.inv.count.dto.InvSeqDto;
import com.wzdigit.wms.wms.domain.inv.count.*;
import com.wzdigit.wms.wms.mapper.inv.count.*;
import com.wzdigit.wms.wms.service.inv.count.util.InvStarUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 盘点单导出BS
 * Created by zyf on 2021/10/13 14:45
 */
@Slf4j
@Service
public class InvCountReportService {
    private static final String STAR = "*";
    private static final String DIV_NO = "DIV_NO";
    private static final String TRSN_ORDER = "TRSN_ORDER";
    private static final String R50 = "R50";
    private static final String D50 = "D50";

    @Value(value = "${default_owner.code}")
    private String DEFAULT_OWNER;
    @Value(value = "${default_owner.name}")
    private String DEFAULT_OWNER_NAME;

    @Autowired
    private InvCountHeaderMapper invCountHeaderMapper;
    @Autowired
    private InvCountDtlMapper invCountDtlMapper;
    @Autowired
    private InvCountDtlGoodsMapper invCountDtlGoodsMapper;
    @Autowired
    private InvCountDifMapper invCountDifMapper;
    @Autowired
    private InvCountDifGoodsMapper invCountDifGoodsMapper;
    @Autowired
    private InvCountScopeMapper invCountScopeMapper;
    @Autowired
    private InvCountApprLogMapper invCountApprLogMapper;
    @Autowired
    private LotnoMapper lotnoMapper;
    @Autowired
    private GoodsMapper goodsMapper;
    @Autowired
    private GoodsLogMapper goodsLogMapper;
    @Autowired
    private GoodsHisMapper goodsHisMapper;
    @Autowired
    private AsnHeaderMapper asnHeaderMapper;
    @Autowired
    private AsnDtlMapper asnDtlMapper;
    @Autowired
    private AsnDtlGoodsMapper asnDtlGoodsMapper;
    @Autowired
    private GdnHeaderMapper gdnHeaderMapper;
    @Autowired
    private GdnDtlMapper gdnDtlMapper;
    @Autowired
    private GdnDtlGoodsMapper gdnDtlGoodsMapper;
    @Autowired
    private TrsnHeaderMapper trsnHeaderMapper;
    @Autowired
    private TrsnDtlMapper trsnDtlMapper;
    @Autowired
    private TrsnDtlGoodsMapper trsnDtlGoodsMapper;
    @Autowired
    private InvLocMapper invLocMapper;

    @Autowired
    private ExportExcelUtils exportExcelUtils;
    @Autowired
    private InvStarUtil invStarUtil;
    @Lazy
    @Autowired
    private InventoryService inventoryService;

    @Reference(version = "${dubbo.consumers.basic.simple.code.rule.api:1.0.0}", check = false)
    private BasicSimpleCodeRuleApi basicSimpleCodeRuleApi;
    @Reference(version = "${dubbo.consumers.basic.data.item.detail.api:1.0.0}", check = false, timeout = 300000)
    private BasicDataItemDetailApi dataItemDetailApi;


    //盘点差异报表
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public PagerInfo<List<CountDifDtlResponse>> searchCountDif(BigDecimal headerId, Pager<?> pager) {
        Page<CountDifDtlResponse> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<CountDifDtlResponse>> pagerInfo = new PagerInfo<>();
        List<CountDifDtlResponse> datas = selectDif(headerId);
        pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(datas);

        return pagerInfo;
    }

    //盘点差异SN报表
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public PagerInfo<List<CountDifGoodsRespone>> searchCountDifGoods(BigDecimal difId, Pager<?> pager) {
        Page<CountDifGoodsRespone> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<CountDifGoodsRespone>> pagerInfo = new PagerInfo<>();
        List<CountDifGoodsRespone> datas = invCountDifGoodsMapper.selectByDifId(difId);
        for (CountDifGoodsRespone data : datas) {
            if (data.getIsExit() != null) {
                InvIsExitEnum isExitEnum = InvIsExitEnum.getEnumByCode(data.getIsExit());
                if (isExitEnum != null) {
                    data.setIsExitStr(isExitEnum.getEnumName());
                }
            }
            if (data.getResult() != null) {
                InvDtlResultEnum resultEnum = InvDtlResultEnum.getEnumByCode(data.getResult());
                if (resultEnum != null) {
                    data.setResultStr(resultEnum.enumName);
                }
            }

        }
        pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(datas);

        return pagerInfo;
    }

    //盘点范围报表
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public PagerInfo<List<CoutnScopeRespnse>> searchCountScope(BigDecimal headerId, Pager<?> pager) {
        Page<CoutnScopeRespnse> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<CoutnScopeRespnse>> pagerInfo = new PagerInfo<>();
        List<CoutnScopeRespnse> datas = selectCountScope(headerId);
        pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(datas);

        return pagerInfo;
    }


    //盘点任务明细报表
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public PagerInfo<List<CountDtlResponse>> searchCountDtl(BigDecimal headerId, Pager<?> pager) {
        Page<CountDtlResponse> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<CountDtlResponse>> pagerInfo = new PagerInfo<>();
        List<CountDtlResponse> datas = selectCountDtl(headerId);
        pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(datas);

        return pagerInfo;
    }

    //复盘任务明细报表
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public PagerInfo<List<ReCountDtlResponse>> searchReCountDtl(BigDecimal headerId, Pager<?> pager) {
        Page<ReCountDtlResponse> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<ReCountDtlResponse>> pagerInfo = new PagerInfo<>();
        List<ReCountDtlResponse> datas = selectReCountDtl(headerId);
        pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(datas);

        return pagerInfo;
    }

    //初盘/复盘SN报表
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public PagerInfo<List<CountDtlGoodsRespone>> searchCountDtlGoods(BigDecimal dtlId, Pager<?> pager) {
        //查询盘点任务信息
        InvCountDtl invCountDtl = invCountDtlMapper.selectOne(new QueryWrapper<InvCountDtl>().eq("INV_COUNT_DTL_ID", dtlId));

        InvCountDtl lastDtl = new InvCountDtl();
        InvCountDtl faterDtl = new InvCountDtl();
        if (invCountDtl.getTaskType().equals(InvTaskTypeEnum.RE_COUNT.code)) {
            //如果是复盘任务，就查询最初的任务ID
            faterDtl = invStarUtil.searchFaterDtl(invCountDtl.getInvCountDtlId());

        } else {
            //如果是初盘任务，就查询最后一次复盘的任务ID
            if (invCountDtl.getReCountId() == null || invCountDtl.getReCountId().signum()==0) {
                //没有复盘过
                lastDtl = null;
            } else {
                //复盘过
                lastDtl = invCountDtlMapper.selectOne(new QueryWrapper<InvCountDtl>().eq("INV_COUNT_DTL_ID", invCountDtl.getReCountId()));
            }
        }


        Page<CountDtlGoodsRespone> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<CountDtlGoodsRespone>> pagerInfo = new PagerInfo<>();
        List<CountDtlGoodsRespone> datas = invCountDtlMapper.slectDtlGoods(dtlId);

        for (CountDtlGoodsRespone data : datas) {
            if (data.getIsExit() != null) {
                InvIsExitEnum isExitEnum = InvIsExitEnum.getEnumByCode(data.getIsExit());
                if (isExitEnum != null) {
                    data.setIsExitStr(isExitEnum.getEnumName());
                }
            }
            if (data.getResult() != null) {
                InvDtlResultEnum resultEnum = InvDtlResultEnum.getEnumByCode(data.getResult());
                if (resultEnum != null) {
                    data.setResultStr(resultEnum.enumName);
                }
            }
            if (invCountDtl.getTaskType().equals(InvTaskTypeEnum.RE_COUNT.code)) {

                data.setReCoutnLoc(data.getCoutnLoc());
                data.setReCountTime(data.getCountTime());
                data.setReCountQty(data.getCountQty());
                data.setReCountBy(data.getCountBy());
                if (invCountDtl.getRelationTaskId()==null||invCountDtl.getRelationTaskId().signum()==0){
                    data.setCoutnLoc(null);
                    data.setCountTime(null);
                    data.setCountQty(null);
                    data.setCountBy(null);
                }
                if (faterDtl!=null){
                    CountDtlGoodsRespone fartherGoods = invCountDtlMapper.slectReDtlGoods(faterDtl.getInvCountDtlId(), data.getGoodsSn());
                    if (fartherGoods != null) {
                        data.setCoutnLoc(fartherGoods.getCoutnLoc());
                        data.setCountTime(fartherGoods.getCountTime());
                        data.setCountQty(fartherGoods.getCountQty());
                        data.setCountBy(fartherGoods.getCountBy());
                    }
                }

            } else {
                if (lastDtl != null) {
                    CountDtlGoodsRespone lastGoods = invCountDtlMapper.slectReDtlGoods(lastDtl.getInvCountDtlId(), data.getGoodsSn());
                    if (lastGoods != null) {
                        data.setReCoutnLoc(lastGoods.getCoutnLoc());
                        data.setReCountTime(lastGoods.getCountTime());
                        data.setReCountQty(lastGoods.getCountQty());
                        data.setReCountBy(lastGoods.getCountBy());
                    }
                }
            }
        }
        pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(datas);

        return pagerInfo;
    }

    //盘点结果汇总报表
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public PagerInfo<List<CountAllResultResponse>> searchAllResult(BigDecimal headerId, Pager<?> pager) {
        Page<CountAllResultResponse> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<CountAllResultResponse>> pagerInfo = new PagerInfo<>();

        List<CountAllResultResponse> datas = selectAllResult(headerId);

        pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(datas);

        return pagerInfo;
    }

    //盘点合并导出
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void exportAll(
            BigDecimal headerId, HttpServletRequest servletRequest,
            HttpServletResponse servletResponse) throws Exception {

        //查询盘点范围
        List<CoutnScopeRespnse> scopeDatas = selectCountScope(headerId);
        //查询盘点结果汇总
        List<CountAllResultResponse> resultDatas = selectAllResult(headerId);
        //查询盘点任务明细
        List<CountDtlResponse> dtlDatas = selectCountDtl(headerId);
        //查询复盘任务明细
        List<ReCountDtlResponse> reDtlDatas = selectReCountDtl(headerId);
        //查询盘点差异
        List<CountDifDtlResponse> difDatas = selectDif(headerId);
        //设置各sheet表头
        String[] scopeHeaders = new String[]{"库区", "库位", "批次号", "物料分类", "物料编码"};
        String[] resultHeaders = new String[]{"物料编码", "物料描述", "工厂代码",
                "供应商", "库存性质", "批次号", "批次属性", "品质状态", "账面数量", "盘点数量", "复盘数量", "差异数", "结果"};
        String[] dtlHeaders = new String[]{"行号", "行状态", "任务类型", "物料编码", "物料描述", "工厂代码", "供应商",
                "库存性质", "批次号", "批次属性", "品质状态", "仓库", "库区", "库位", "账面数量", "盘点结果", "盘点时间", "是否复盘"};
        String[] reDtlHeaders = new String[]{"行号", "行状态", "任务类型", "初盘单行号", "物料编码", "物料描述",
                "工厂代码", "供应商", "库存性质", "批次号", "批次属性", "品质状态", "仓库", "库区", "库位",
                "账面数量", "实盘数量", "盘点结果", "盘点人", "盘点时间"};
        String[] difHeaders = new String[]{"行号", "行状态", "任务类型", "物料编码", "物料描述", "工厂代码", "供应商",
                "库存性质", "批次号", "批次属性", "品质状态", "仓库", "库区", "库位", "账面数量", "实盘数量", "盘点结果",
                "是否复盘", "复盘数量", "复盘结果", "盘点人", "盘点时间", "复盘人", "复盘时间"};
        //合并导出
        List<ExportExcleDTO> list = new ArrayList<>();
        ExportExcleDTO scopeDto = new ExportExcleDTO();
        scopeDto.setTitle("盘点范围");
        scopeDto.setHeaders(scopeHeaders);
        scopeDto.setDataSet(scopeDatas);
        ExportExcleDTO resultDto = new ExportExcleDTO();
        resultDto.setTitle("盘点结果汇总");
        resultDto.setHeaders(resultHeaders);
        resultDto.setDataSet(resultDatas);
        ExportExcleDTO dtlDto = new ExportExcleDTO();
        dtlDto.setTitle("盘点任务明细");
        dtlDto.setHeaders(dtlHeaders);
        dtlDto.setDataSet(dtlDatas);
        ExportExcleDTO reDtlDto = new ExportExcleDTO();
        reDtlDto.setTitle("复盘任务明细");
        reDtlDto.setHeaders(reDtlHeaders);
        reDtlDto.setDataSet(reDtlDatas);
        ExportExcleDTO dfiDto = new ExportExcleDTO();
        dfiDto.setTitle("盘点差异");
        dfiDto.setHeaders(difHeaders);
        dfiDto.setDataSet(difDatas);
        list.add(scopeDto);
        list.add(resultDto);
        list.add(dtlDto);
        list.add(reDtlDto);
        list.add(dfiDto);

        ServletOutputStream out = servletResponse.getOutputStream();
        String userAgent = servletRequest.getHeader("USER-AGENT");
        String fileName = "盘点信息汇总表";
        if (userAgent.contains("Mozilla")) {
            fileName = new String(fileName.getBytes(), "ISO8859-1");
        } else {
            fileName = URLEncoder.encode(fileName, "utf8");
        }
        servletResponse.setContentType("application/octet-stream");
        servletResponse.setHeader("Content-Disposition", "attachment;fileName=" + fileName + ".xlsx");
        servletResponse.flushBuffer();
        exportExcelUtils.exportExcel(list, out);

    }

    //查询盘点范围【复用】
    private List<CoutnScopeRespnse> selectCountScope(BigDecimal headerId) {
        List<CoutnScopeRespnse> datas = invCountScopeMapper.selectReport(headerId);
        for (CoutnScopeRespnse data : datas) {
            if (STAR.equals(data.getArea())) {
                data.setArea("所有库区");
            }
            if (STAR.equals(data.getLoc())) {
                data.setLoc("所有库位");
            }
            if (STAR.equals(data.getLotNo())) {
                data.setLotNo("所有批次");
            }
            if (STAR.equals(data.getSkuCategory())) {
                data.setSkuCategory("所有物料分类");
            }
            if (STAR.equals(data.getSku())) {
                data.setSku("所有物料编码");
            }
        }
        return datas;
    }


    //查询盘点差异【复用】
    private List<CountDifDtlResponse> selectDif(BigDecimal headerId) {
        List<CountDifDtlResponse> datas = invCountDifMapper.selectByHedeerId(headerId);
        for (CountDifDtlResponse data : datas) {
            if (data.getStatusInt() != null) {
                InvDifStatusEnum difStatusEnum = InvDifStatusEnum.getEnumByCode(data.getStatusInt());
                if (difStatusEnum != null) {
                    data.setStatus(difStatusEnum.getEnumName());
                }
            }
            if (data.getTaskType() != null) {
                InvTaskTypeEnum taskTypeEnum = InvTaskTypeEnum.getEnumByCode(data.getTaskType());
                if (taskTypeEnum != null) {
                    data.setTaskStr(taskTypeEnum.getEnumName());
                }
            }
            if (data.getQaStatus() != null) {
                QaStatusEnum qaStatusEnum = QaStatusEnum.getEnumByCode(data.getQaStatus());
                if (qaStatusEnum != null) {
                    data.setQaStatusStr(qaStatusEnum.getEnumName());
                }
            }
            if (data.getResult() != null) {
                InvDtlResultEnum resultEnum = InvDtlResultEnum.getEnumByCode(data.getResult());
                if (resultEnum != null) {
                    data.setResultStr(resultEnum.enumName);
                }
            }
            if (data.getReCount() != null) {
                InvIsReplayEnum replayEnum = InvIsReplayEnum.getEnumByCode(data.getReCount());
                if (replayEnum != null) {
                    data.setReCountStr(replayEnum.enumName);

                }
            }
            if (data.getReResult() != null) {
                InvDtlResultEnum reResultEnum = InvDtlResultEnum.getEnumByCode(data.getReResult());
                if (reResultEnum != null) {
                    data.setReResultStr(reResultEnum.enumName);
                }
            }

            BigDecimal accountQty=BigDecimal.ZERO;
            if (data.getAccountQty()!=null){
                accountQty=data.getAccountQty();
            }

            if (data.getReCountQty()==null){
                data.setDifQty(data.getCountQty()!=null?data.getCountQty().subtract(accountQty):BigDecimal.ZERO.subtract(accountQty));
            }else {
                data.setDifQty(data.getReCountQty().subtract(accountQty));
            }

        }
        return datas;
    }

    //盘点任务明细报表【复用】
    private List<CountDtlResponse> selectCountDtl(BigDecimal headerId) {
        List<CountDtlResponse> datas = invCountDtlMapper.selectDtlReport(headerId);
        for (CountDtlResponse data : datas) {
            if (data.getStatusInt() != null) {
                InvDtlStatusEnum dtlStatusEnum = InvDtlStatusEnum.getEnumByCode(data.getStatusInt());
                if (dtlStatusEnum != null) {
                    data.setStatus(dtlStatusEnum.getEnumName());
                }
            }
            if (data.getTaskType() != null) {
                InvTaskTypeEnum taskTypeEnum = InvTaskTypeEnum.getEnumByCode(data.getTaskType());
                if (taskTypeEnum != null) {
                    data.setTypeStr(taskTypeEnum.getEnumName());
                }
            }
            if (data.getQaStatus() != null) {
                QaStatusEnum qaStatusEnum = QaStatusEnum.getEnumByCode(data.getQaStatus());
                if (qaStatusEnum != null) {
                    data.setQaStatusStr(qaStatusEnum.getEnumName());
                }
            }
            if (data.getResult() != null) {
                InvDtlResultEnum resultEnum = InvDtlResultEnum.getEnumByCode(data.getResult());
                if (resultEnum != null) {
                    data.setResultStr(resultEnum.getEnumName());
                }
            }
            if (data.getIsReCountInt() != null) {
                InvIsReplayEnum replayEnum = InvIsReplayEnum.getEnumByCode(data.getIsReCountInt());
                if (replayEnum != null) {
                    data.setIsReCount(replayEnum.getEnumName());
                }
            }
            if (data.getStatusInt() != null) {
                InvDtlStatusEnum dtlStatusEnum = InvDtlStatusEnum.getEnumByCode(data.getStatusInt());
                if (dtlStatusEnum != null) {
                    data.setStatus(dtlStatusEnum.enumName);
                }
            }
        }
        return datas;
    }

    //复盘任务明细报表【复用】
    private List<ReCountDtlResponse> selectReCountDtl(BigDecimal headerId) {
        InvCountDtl faterDtl = null;
        List<ReCountDtlResponse> datas = invCountDtlMapper.selectReDtlReport(headerId);
        for (ReCountDtlResponse data : datas) {
            if (data.getStatusInt() != null) {
                InvDtlStatusEnum dtlStatusEnum = InvDtlStatusEnum.getEnumByCode(data.getStatusInt());
                if (dtlStatusEnum != null) {
                    data.setStatus(dtlStatusEnum.getEnumName());
                }
            }
            if (data.getTaskType() != null) {
                InvTaskTypeEnum taskTypeEnum = InvTaskTypeEnum.getEnumByCode(data.getTaskType());
                if (taskTypeEnum != null) {
                    data.setTypeStr(taskTypeEnum.getEnumName());
                }
            }
            if (data.getQaStatus() != null) {
                QaStatusEnum qaStatusEnum = QaStatusEnum.getEnumByCode(data.getQaStatus());
                if (qaStatusEnum != null) {
                    data.setQaStatusStr(qaStatusEnum.getEnumName());
                }
            }
            if (data.getResult() != null) {
                InvDtlResultEnum resultEnum = InvDtlResultEnum.getEnumByCode(data.getResult());
                if (resultEnum != null) {
                    data.setResultStr(resultEnum.getEnumName());
                }
            }
            faterDtl = invStarUtil.searchFaterDtl(data.getDtlId());
            if (faterDtl != null) {
                data.setRelationLine(faterDtl.getInvCountLineNo());
            }
            if (data.getStatusInt() != null) {
                InvDtlStatusEnum dtlStatusEnum = InvDtlStatusEnum.getEnumByCode(data.getStatusInt());
                if (dtlStatusEnum != null) {
                    data.setStatus(dtlStatusEnum.enumName);
                }
            }
        }
        return datas;
    }

    //查询盘点结果【复用】
    private List<CountAllResultResponse> selectAllResult(BigDecimal headerId) {
        List<CountAllResultResponse> datas = invCountDtlMapper.slectAllResult(headerId);
        BigDecimal zero = BigDecimal.ZERO;
        for (CountAllResultResponse data : datas) {
            if (data.getQaStatusInt() != null) {
                QaStatusEnum qaStatusEnum = QaStatusEnum.getEnumByCode(data.getQaStatusInt());
                if (qaStatusEnum != null) {
                    data.setQaStatus(qaStatusEnum.enumName);
                }
            }
            if (data.getResult() != null) {
                InvDtlResultEnum resultEnum = InvDtlResultEnum.getEnumByCode(data.getResult());
                if (resultEnum != null) {
                    data.setResultStr(resultEnum.enumName);
                }
            }


            if (data.getReCountQty() == null) {
                data.setDifQty(data.getCountQty().subtract(data.getAcCountQty()));
            } else {
                data.setDifQty(data.getReCountQty().subtract(data.getAcCountQty()));
            }
        }
        return datas;
    }

    //盘点结果-盘点结果明细
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public PagerInfo<List<CountAprResultResponse>> searchAprResultDtl(BigDecimal headerId, Pager<?> pager) {
        Page<CountAprResultResponse> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<CountAprResultResponse>> pagerInfo = new PagerInfo<>();

        List<CountAprResultResponse> datas = invCountDtlMapper.selectAprResultDtl(headerId);

        for (CountAprResultResponse data : datas) {
            if (data.getQaStatus() != null) {
                QaStatusEnum qaStatusEnum = QaStatusEnum.getEnumByCode(data.getQaStatus());
                if (qaStatusEnum != null) {
                    data.setQaStatusStr(qaStatusEnum.enumName);
                }
            }
            if (data.getResult() != null) {
                InvDtlResultEnum resultEnum = InvDtlResultEnum.getEnumByCode(data.getResult());
                if (resultEnum != null) {
                    data.setResultStr(resultEnum.enumName);
                }
            }
            if (data.getReResult() != null) {
                InvDtlResultEnum reResultEnum = InvDtlResultEnum.getEnumByCode(data.getReResult());
                if (reResultEnum != null) {
                    data.setReResultStr(reResultEnum.enumName);
                }
            }
            //设置盘点次数
            data.setReQty(invStarUtil.searchReCountNumer(data.getReCountId()));
            //设置差异数
            if (data.getReCountQty() == null || (data.getReCountQty().compareTo(BigDecimal.ZERO) == 0)) {
                data.setDifQty(data.getCountQty().subtract(data.getAccountQty()));
            } else {
                data.setDifQty(data.getReCountQty().subtract(data.getAccountQty()));
            }

            //置空初盘任务的复盘数据
            if (data.getReCountId() == null || (data.getReCountId().compareTo(BigDecimal.ZERO) == 0)) {
                data.setReCountQty(null);
                data.setReCountTime(null);
                data.setReCountBy(null);
            } else {
                data.setDtlId(data.getReCountId());
            }
        }

        pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(datas);

        return pagerInfo;
    }

    //盘点结果-盘点差异
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public PagerInfo<List<CountAprResultResponse>> searchAprDif(BigDecimal headerId, Pager<?> pager) {
        Page<CountAprResultResponse> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<CountAprResultResponse>> pagerInfo = new PagerInfo<>();

        List<CountAprResultResponse> datas = invCountDifMapper.selectAprResultDif(headerId);

        for (CountAprResultResponse data : datas) {
            if (data.getResult()==null){
                data.setResult(data.getFirstResult());
            }
            if (data.getQaStatus() != null) {
                QaStatusEnum qaStatusEnum = QaStatusEnum.getEnumByCode(data.getQaStatus());
                if (qaStatusEnum != null) {
                    data.setQaStatusStr(qaStatusEnum.enumName);
                }
            }
            if (data.getResult() != null) {
                InvDtlResultEnum resultEnum = InvDtlResultEnum.getEnumByCode(data.getResult());
                if (resultEnum != null) {
                    data.setResultStr(resultEnum.enumName);
                }
            }
            if (data.getReResult() != null) {
                InvDtlResultEnum reResultEnum = InvDtlResultEnum.getEnumByCode(data.getReResult());
                if (reResultEnum != null) {
                    data.setReResultStr(reResultEnum.enumName);
                }
            }
            if (data.getDifResult() != null) {
                InvDifAdjResultEnum adjEnum = InvDifAdjResultEnum.getEnumByCode(data.getDifResult());
                if (adjEnum != null) {
                    data.setDifStr(adjEnum.enumName);
                }
            }
            //设置盘点次数
           // data.setReQty(invStarUtil.searchReCountNumer(data.getReCountId()));
            //设置差异数
            if (data.getReCountQty() == null || (data.getReCountQty().compareTo(BigDecimal.ZERO) == 0)) {
                data.setDifQty(data.getAccountQty().subtract(data.getCountQty()));
            } else {
                if (data.getReCountQty()==null){
                    data.setDifQty(data.getAccountQty().subtract(data.getCountQty()));
                }else {
                    data.setDifQty(data.getAccountQty().subtract(data.getReCountQty()));
                }
            }
        }

        pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(datas);

        return pagerInfo;
    }

    //盘点履历
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public PagerInfo<List<InvSeqDto>> searchInvSeq(BigDecimal dtlId, Pager<?> pager) throws Exception {
        List<BigDecimal> dtlIdList = new ArrayList<>();

        InvCountDtl dtl = invCountDtlMapper.selectOne(new QueryWrapper<InvCountDtl>().eq("INV_COUNT_DTL_ID", dtlId));
        while (dtl.getRelationTaskId() != null) {
            dtl = invCountDtlMapper.selectOne(new QueryWrapper<InvCountDtl>().eq("INV_COUNT_DTL_ID", dtl.getRelationTaskId()));
            dtlIdList.add(dtl.getInvCountDtlId());
        }

        Page<InvSeqDto> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<InvSeqDto>> pagerInfo = new PagerInfo<>();

        List<InvSeqDto> datas = invCountDtlMapper.selectSeqDto(dtlIdList);
        for (InvSeqDto data : datas) {
            if (data.getResult() != null) {
                InvDtlResultEnum resultEnum = InvDtlResultEnum.getEnumByCode(data.getResult());
                if (resultEnum != null) {
                    data.setResultStr(resultEnum.enumName);
                }
            }
        }


        pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(datas);

        return pagerInfo;
    }


    //结果审核
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Result<String> resultApprNew(ResultApprDto dto, HttpServletRequest servletRequest) throws Exception {
        Boolean falg = dto.getResult().equals(InvAprResultEnum.PASS.code);
        List<BigDecimal> headerIds = dto.getHeaderIds();

        if (CollectionUtil.isEmpty(headerIds)) {
            Shift.fatal("请勾选要结果审核的单据");
        }
        List<InvCountHeader> headerList = invCountHeaderMapper.selectList(new QueryWrapper<InvCountHeader>().in("INV_COUNT_HEADER_ID", headerIds));
        List<Integer> statusList = headerList.stream().map(t -> t.getStatus()).distinct().collect(Collectors.toList());
        if (statusList.size() > 1) {
            Shift.fatal("仅[" + InvHeaderStatusEnum.RESULT_WAIT_APPROVED.enumName + "]的盘点单能结果审核!");
        }
        if (!statusList.get(0).equals(InvHeaderStatusEnum.RESULT_WAIT_APPROVED.code)) {
            Shift.fatal("仅[" + InvHeaderStatusEnum.RESULT_WAIT_APPROVED.enumName + "]的盘点单能结果审核!");
        }
        Date nowDate = new Date();
        String loginName = HttpSessionUtil.getLoginName(servletRequest);

        //存在差异审核通过的主档集合
        List<BigDecimal> difHeaderIds = new ArrayList<>();
        //无差异审核通过的主档集合(自动关单)
        List<BigDecimal> closeHeaderIds = new ArrayList<>();

        //更新审核状态
        if (falg) {
            invCountHeaderMapper.updateHeaderAppr(
                    loginName, InvHeaderStatusEnum.RESULT_SUCCESS_APPROVED.code, dto.getResult(), headerIds);
        } else {
            invCountHeaderMapper.updateHeaderAppr(
                    loginName, InvHeaderStatusEnum.RESULT_FAIL_APPROVED.code, dto.getResult(), headerIds);
        }

        for (BigDecimal headerId : headerIds) {
            //记录审核日志
            InvCountApprLog apprLog = new InvCountApprLog();
            apprLog.setInvCountHeaderId(headerId);
            apprLog.setComments(dto.getComments());
            apprLog.setResult(dto.getResult());
            apprLog.setApproveTime(nowDate);
            apprLog.setApproveBy(loginName);
            invCountApprLogMapper.insert(apprLog);

            //记录差异表
            if (falg) {
                Boolean closeFlage = true;
                String divNo = basicSimpleCodeRuleApi.GenerateCode(DIV_NO);
                Integer lineNo = 1;
                //查询只初盘过或者最后一次复盘的单据
                QueryWrapper<InvCountDtl> lastQueryWrapper = new QueryWrapper<>();
                lastQueryWrapper.eq("INV_COUNT_HEADER_ID", headerId);
                lastQueryWrapper.eq("RE_COUNT_ID", 0);
                List<InvCountDtl> lastDtlList = invCountDtlMapper.selectList(lastQueryWrapper);
                log.info("[" + headerId + "]生成差异单");
                System.out.println(lastDtlList);
                for (InvCountDtl invCountDtl : lastDtlList) {
                    log.info("ZYF:"+invCountDtl);
                    List<InvCountDtlGoods> lastGoodsList = invCountDtlGoodsMapper.selectList
                            (new QueryWrapper<InvCountDtlGoods>().eq("INV_COUNT_DTL_ID", invCountDtl.getInvCountDtlId()).ne("RESULT", 1));
                    if (lastGoodsList == null) {
                        continue;
                    }
                    if (lastGoodsList.size() == 0) {
                        continue;
                    }
                    closeFlage = false;
                    InvCountDif dif = new InvCountDif();
                    dif.setInvCountDtlId(invCountDtl.getInvCountDtlId());
                    dif.setDifAdjDocNo(divNo);
                    dif.setDifAdjDocLineNo(lineNo++);
                    dif.setFactory(invCountDtl.getFactory());
                    dif.setSkuId(invCountDtl.getSkuId());
                    dif.setVendor(invCountDtl.getVendor());
                    dif.setInvAttr(invCountDtl.getInvAttr());
                    dif.setLotno(invCountDtl.getLotno());
                    dif.setWhsId(invCountDtl.getWhsId());
                    dif.setZoneId(invCountDtl.getZoneId());
                    dif.setLocId(invCountDtl.getLocId());
                    dif.setAccountQty(invCountDtl.getAccountQty());
                    dif.setQaStatus(invCountDtl.getQaStatus());
                    dif.setCreateUser(loginName);
                    dif.setCreateTime(nowDate);
                    dif.setUnit(invCountDtl.getUnit());
                    dif.setStatus(InvDifDtlStatusEnum.CREATE.code);

                    if (invCountDtl.getTaskType().equals(InvTaskTypeEnum.ONCE_COUNT.code)) {
                        //仅初盘过
                        dif.setCountQty(invCountDtl.getCountQty());
                        dif.setResult(invCountDtl.getResult());
                        dif.setCountBy(invCountDtl.getCountBy());
                        dif.setCountTime(invCountDtl.getCountTime());
                        dif.setReCountNumber(0);
                        invCountDifMapper.insert(dif);
                        for (InvCountDtlGoods dtlGoods : lastGoodsList) {
                            InvCountDifGoods difGoods=new InvCountDifGoods();
                            difGoods.setInvCountDifId(dif.getInvCountDifId());
                            difGoods.setGoodsSn(dtlGoods.getGoodsSn());
                            difGoods.setGoodsId(dtlGoods.getGoodsId());
                            difGoods.setAccountQty(dtlGoods.getAccountQty());
                            difGoods.setCountQty(dtlGoods.getCountQty());
                            difGoods.setAccountLoc(dtlGoods.getAccountLoc());
                            difGoods.setCountLoc(dtlGoods.getCountLoc());
                            difGoods.setIsExist(dtlGoods.getIsExist());
                            difGoods.setCountBy(dif.getCountBy());
                            difGoods.setCountTime(dif.getCountTime());
                            difGoods.setComments(dtlGoods.getComments());
                            difGoods.setResult(dtlGoods.getResult());
                            difGoods.setStatus(InvDifGoodsStatusEnum.NO.code);
                            difGoods.setCreateUser(loginName);
                            difGoods.setCreateTime(nowDate);
                            invCountDifGoodsMapper.insert(difGoods);
                        }

                    } else {
                        //复盘过
                        dif.setReCountQty(invCountDtl.getCountQty());
                        dif.setReResult(invCountDtl.getResult());
                        dif.setReCountBy(invCountDtl.getCountBy());
                        dif.setReCountTime(invCountDtl.getCountTime());
                        dif.setReCountNumber(0);
                        InvCountDtl faterDtl = null;
                        if (invCountDtl.getRelationTaskId() != null&&(invCountDtl.getRelationTaskId().signum()!=0)) {
                            //查询最父级盘点任务

                            faterDtl = invStarUtil.searchFaterDtl(invCountDtl.getInvCountDtlId());
                            log.info("ZYF父:"+faterDtl);
                            dif.setReCountNumber(invStarUtil.searchReCountNumer(invCountDtl.getInvCountDtlId()));
                            dif.setCountQty(faterDtl.getCountQty());
                            dif.setResult(faterDtl.getResult());
                            dif.setCountBy(faterDtl.getCountBy());
                            dif.setCountTime(faterDtl.getCountTime());
                        }

                        invCountDifMapper.insert(dif);
                        for (InvCountDtlGoods dtlGoods : lastGoodsList) {
                            InvCountDifGoods difGoods=new InvCountDifGoods();
                            difGoods.setInvCountDifId(dif.getInvCountDifId());
                            difGoods.setGoodsSn(dtlGoods.getGoodsSn());
                            difGoods.setGoodsId(dtlGoods.getGoodsId());
                            difGoods.setAccountQty(dtlGoods.getAccountQty());
                            difGoods.setReCountQty(dtlGoods.getCountQty());
                            difGoods.setAccountLoc(dtlGoods.getAccountLoc());
                            difGoods.setReCountLoc(dtlGoods.getCountLoc());
                            difGoods.setIsExist(dtlGoods.getIsExist());
                            difGoods.setReCountBy(dtlGoods.getCountBy());
                            difGoods.setReCountTime(dtlGoods.getCountTime());
                            difGoods.setComments(dtlGoods.getComments());
                            difGoods.setResult(dtlGoods.getResult());
                            difGoods.setStatus(InvDifGoodsStatusEnum.NO.code);
                            difGoods.setCreateUser(loginName);
                            difGoods.setCreateTime(nowDate);
                            if (faterDtl!=null){
                                //查询初盘任务对应的SN
                                InvCountDtlGoods firstGoods = invCountDtlGoodsMapper.selectOne(new QueryWrapper<InvCountDtlGoods>().eq("INV_COUNT_DTL_ID", faterDtl.getInvCountDtlId()).eq("GOODS_SN", dtlGoods.getGoodsSn()));
                                if (firstGoods!=null){
                                    difGoods.setCountBy(firstGoods.getCountBy());
                                    difGoods.setCountQty(firstGoods.getCountQty());
                                    difGoods.setCountLoc(firstGoods.getCountLoc());
                                    difGoods.setCountTime(firstGoods.getCountTime());
                                }
                            }
                            invCountDifGoodsMapper.insert(difGoods);
                        }
                    }
                }

                if (closeFlage){
                    closeHeaderIds.add(headerId);
                }else {
                    difHeaderIds.add(headerId);
                }
            }


            //审核通过无差异自动关闭
            if (!CollectionUtil.isEmpty(closeHeaderIds)) {
                invCountHeaderMapper.updateHeaderAppr(
                        loginName, InvHeaderStatusEnum.CLOSE.code, dto.getResult(), headerIds);
            }
            //审核通过有差异的更新状态为差异待处理
            if (!CollectionUtil.isEmpty(difHeaderIds)) {
                invCountHeaderMapper.updateHeaderAppr(
                        loginName, InvHeaderStatusEnum.WAIT_DIVERSITY.code, dto.getResult(), headerIds);
            }
            /*        Shift.fatal("XXXXXXXXXX");*/


        }
        return new Result<>("审核成功!");
    }

        //盘点差异调账明细
        @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
        public List<CountAprResultResponse> searchDifDtl (BigDecimal headerId) throws Exception {
            List<CountAprResultResponse> datas = invCountDifMapper.selectAprResultDif(headerId);

            for (CountAprResultResponse data : datas) {
                if (data.getResult()==null){
                    data.setResult(data.getFirstResult());
                }
                if (data.getQaStatus() != null) {
                    QaStatusEnum qaStatusEnum = QaStatusEnum.getEnumByCode(data.getQaStatus());
                    if (qaStatusEnum != null) {
                        data.setQaStatusStr(qaStatusEnum.enumName);
                    }
                }

                if (data.getResult() != null) {
                    InvDtlResultEnum resultEnum = InvDtlResultEnum.getEnumByCode(data.getResult());
                    if (resultEnum != null) {
                        data.setResultStr(resultEnum.enumName);
                    }
                }

                if (data.getDifResult() != null) {
                  //  System.out.println(data.getDifResult() +"-----------");
                    InvDifAdjResultEnum adjEnum = InvDifAdjResultEnum.getEnumByCode(data.getDifResult());
                    if (adjEnum != null) {
                        data.setDifResultStr(adjEnum.enumName);
                    }
                }
                //设置盘点次数
               // data.setReQty(invStarUtil.searchReCountNumer(data.getReCountId()));
                //设置差异数
                if (data.getReCountQty() == null || (data.getReCountQty().compareTo(BigDecimal.ZERO) == 0)) {
                    data.setDifQty(data.getCountQty().subtract(data.getAccountQty()));
                } else {
                    data.setDifQty(data.getReCountQty().subtract(data.getAccountQty()));
                }
                data.setDifStr(data.getDifNo() +"/"+ data.getLineNo());
            }

            return datas;
        }


        //盘点调账【last】
        @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
        public Result<String> dfiAdjLast (List < BigDecimal > hederIds, HttpServletRequest servletRequest) throws
        Exception {
            Date nowDate = new Date();
            String loginName = HttpSessionUtil.getLoginName(servletRequest);

            //校验主档状态
            List<InvCountHeader> headerList = invCountHeaderMapper.selectList
                    (new QueryWrapper<InvCountHeader>().in("INV_COUNT_HEADER_ID", hederIds));
            List<Integer> statusList = headerList.stream().map(t -> t.getStatus()).collect(Collectors.toList());
            if (statusList.size() > 1) {
                Shift.fatal("仅[" + InvHeaderStatusEnum.WAIT_DIVERSITY.enumName + "]的盘点单能调账!");
            }
            if (!statusList.get(0).equals(InvHeaderStatusEnum.WAIT_DIVERSITY.code)) {
                Shift.fatal("仅[" + InvHeaderStatusEnum.WAIT_DIVERSITY.enumName + "]的盘点单能调账!");
            }

            List<Integer> granList = headerList.stream().map(t -> t.getCountGranularity()).collect(Collectors.toList());
            if (granList.size() > 1) {
                Shift.fatal("仅[" + InvGranularityEnum.NORMAL_GRAN.enumName + "]的盘点单能调账!");
            }
            if (!granList.get(0).equals(InvGranularityEnum.NORMAL_GRAN.code)) {
                Shift.fatal("仅[" + InvGranularityEnum.NORMAL_GRAN.enumName + "]的盘点单能调账!");
            }


            for (InvCountHeader header : headerList) {
                Integer ownerId = header.getOwner();
                //盘点入库单
                AsnHeader asnHeader = null;
                //盘点出库单
                GdnHeader gdnHeader = null;
                int asnLine = 1;
                int gdnLine = 1;

                List<BigDecimal> dtlIds = invCountDtlMapper.selectList(
                        new QueryWrapper<InvCountDtl>().eq("INV_COUNT_HEADER_ID", header.getInvCountHeaderId())).
                        stream().map(t -> t.getInvCountDtlId()).collect(Collectors.toList());
                //查询需要调账的差异单
                QueryWrapper<InvCountDif> difQueryWrapper = new QueryWrapper<>();
                difQueryWrapper.in("INV_COUNT_DTL_ID", dtlIds);
                List<InvCountDif> difList = invCountDifMapper.selectList(difQueryWrapper);

                for (InvCountDif dif : difList) {

                    log.info("[" + dif.getDifAdjDocNo() + "/" + dif.getDifAdjDocLineNo() + "]差异调账!");
                    if (dif.getReCountQty() == null) {
                        dif.setReCountQty(dif.getCountQty());
                    }

                    if (dif.getReResult() == null) {
                        dif.setReResult(dif.getResult());
                    }

                    String poNo = "";
                        String soNo = "";
                        String soItem = "";
                        if (dif.getLotno() != null) {
                        Lotno lotno = lotnoMapper.selectOne(new QueryWrapper<Lotno>().eq("LOTNO", dif.getLotno()));
                        if (lotno == null) {
                            Shift.fatal("查无差异单[" + dif.getDifAdjDocNo() + "]对应的批次号信息!");
                        }
                        String lotAttrCode = lotno.getLotAttrCode();
                        JSONObject jsonObject = new JSONObject(lotAttrCode);
                        poNo = jsonObject.getString("PO_NO");
                        soNo = jsonObject.getString("SO_NO");
                        soItem = jsonObject.getString("SO_ITEM");
                    }

                    //查询实际库存是否与账面数一致
                    SearchInvRequest searchInvRequest = new SearchInvRequest();
                    searchInvRequest.setWhsId(dif.getWhsId());
                    searchInvRequest.setSkuId(dif.getSkuId());
                    searchInvRequest.setFactory(dif.getFactory());
                    searchInvRequest.setVendorId(dif.getVendor());
                    searchInvRequest.setLotno(dif.getLotno());
                    searchInvRequest.setInvAttr(dif.getInvAttr());
                    searchInvRequest.setQaStatus(dif.getQaStatus());
                    searchInvRequest.setOwnerId(ownerId);
                    searchInvRequest.setLocId(dif.getLocId());

                    if (!dif.getReResult().equals(InvDtlResultEnum.NEW_PROFIT.code)) {
                        BigDecimal realQty = invLocMapper.selectQty(searchInvRequest);

                        if (!(realQty.compareTo(dif.getAccountQty()) == 0)) {
                            log.info("[" + dif.getDifAdjDocNo() + "/" + dif.getDifAdjDocLineNo() + "]实际库存与账面库存不一致!");
                            Shift.fatal("[" + dif.getDifAdjDocNo() + "/" + dif.getDifAdjDocLineNo() + "]实际库存与账面库存不一致!");
                        }
                    }




                    UpdateInventoryInputDto inventoryInputDto = new UpdateInventoryInputDto();
                    BigDecimal qty = dif.getReCountQty().subtract(dif.getAccountQty());
                    inventoryInputDto.setWhsId(dif.getWhsId());
                    inventoryInputDto.setLocId(dif.getLocId());
                    inventoryInputDto.setOwner(ownerId);
                    inventoryInputDto.setSkuId(dif.getSkuId());
                    inventoryInputDto.setFactory(dif.getFactory());
                    inventoryInputDto.setVendorId(dif.getVendor());
                    inventoryInputDto.setLotNo(dif.getLotno());
                    inventoryInputDto.setInvAttr(dif.getInvAttr());
                    inventoryInputDto.setQaStatus(dif.getQaStatus());
                    inventoryInputDto.setOperator(loginName);
                    inventoryInputDto.setQty(qty);
                    inventoryInputDto.setUnit(dif.getUnit());


                    inventoryService.updateLocInventroy(inventoryInputDto);
                    inventoryService.updateZoneInventory(inventoryInputDto);

                    //查询需要调账的SN
                    QueryWrapper<InvCountDifGoods> goodsQueryWrapper = new QueryWrapper<>();
                    goodsQueryWrapper.ne("RESULT", InvDtlResultEnum.NORMAL.code);
                    goodsQueryWrapper.eq("INV_COUNT_DIF_ID", dif.getInvCountDifId());
                    List<InvCountDifGoods> difGoodsList = invCountDifGoodsMapper.selectList(goodsQueryWrapper);

                    for (InvCountDifGoods difGoods : difGoodsList) {
                        if (difGoods.getReCountQty() == null) {
                            difGoods.setReCountQty(difGoods.getCountQty());
                        }
                        Goods newGoods = new Goods();
                        String oldJson = "";
                        String newJson = "";
                        if (difGoods.getResult().equals(InvDtlResultEnum.NEW_PROFIT.code)) {
                            //新增盘盈，直接添加入GOODS表
                            newGoods.setGoodsSn(difGoods.getGoodsSn());
                            newGoods.setOwner(ownerId);
                            newGoods.setSkuId(dif.getSkuId());
                            newGoods.setFactory(dif.getFactory());
                            newGoods.setVendorId(dif.getVendor());
                            newGoods.setStockInDate(nowDate);
                            newGoods.setLotno(dif.getLotno());
                            newGoods.setInvAttr(dif.getInvAttr());
                            newGoods.setQaStatus(dif.getQaStatus());
                            newGoods.setPoNo(poNo);
                            newGoods.setSoNo(soNo);
                            newGoods.setSoItem(soItem);
                            newGoods.setQty(difGoods.getReCountQty());
                            newGoods.setUnit(dif.getUnit());
                            if (dif.getLocId() != null) {
                                newGoods.setStatus(GoodsStatusEnum.HAS_UP.code);
                            } else {
                                newGoods.setStatus(GoodsStatusEnum.WAIT_UP.code);
                            }
                            newGoods.setWhsId(dif.getWhsId());
                            newGoods.setLocId(dif.getLocId());
                            newGoods.setIsHold(IsHoldEnum.No.code);
                            newGoods.setIsOriginalPackage(0);
                            newGoods.setCreateUser(loginName);
                            newGoods.setCreateTime(nowDate);
                            goodsMapper.insert(newGoods);
                            newJson = JSON.toJSONString(newGoods);
                            //更新difDtlGoods表的goodsId
                            invCountDtlGoodsMapper.updateGoodsId(dif.getInvCountDifId(), difGoods.getGoodsSn(), newGoods.getGoodsId());
                        } else {
                            QueryWrapper<Goods> goodsQuety = new QueryWrapper<Goods>().eq("GOODS_SN", difGoods.getGoodsSn());
                            Goods goods = goodsMapper.selectOne(goodsQuety);
                            oldJson = JSON.toJSONString(goods);
                            if (difGoods.getReCountQty().compareTo(BigDecimal.ZERO) == 1) {
                                //更新对应SN的数量
                                goods.setQty(difGoods.getReCountQty());
                                goods.setModifyTime(nowDate);
                                goods.setModifyUser(loginName);
                                newJson = JSON.toJSONString(goods);
                                goodsMapper.update(goods, goodsQuety);
                            } else {
                                //没有盘到的SN自动出库
                                GoodsHis goodsHis = new GoodsHis();
                                BeanUtils.copyProperties(goods, goodsHis);
                                goodsHis.setLogCreateUser(loginName);
                                goodsHis.setLogCreateTime(nowDate);
                                goodsHisMapper.insert(goodsHis);
                                goodsMapper.delete(goodsQuety);
                            }
                        }

                        //记录日志
                        GoodsLog goodsLog = new GoodsLog();
                        goodsLog.setGoodsSn(difGoods.getGoodsSn());
                        goodsLog.setOpCode(OpCodeEnum.COUNT.getCode());
                        goodsLog.setReason("单号差异单[" + dif.getDifAdjDocNo() + "/" + dif.getDifAdjDocLineNo() + "]调账");
                        String goodsJson = "未更新的:" + oldJson + ",更新的:" + newJson;
                        goodsLog.setUpdateContent(goodsJson);
                        goodsLog.setOperator(loginName);
                        goodsLog.setCreateUser(loginName);
                        goodsLog.setCreateTime(nowDate);
                        goodsLog.setModifyUser(loginName);
                        goodsLog.setModifyTime(nowDate);
                        goodsLogMapper.insert(goodsLog);

                    }

                    //再查一次获取goodsId取盘亏&盘盈的difGoods
                    QueryWrapper<InvCountDifGoods> addQuery = new QueryWrapper<>();
                    addQuery.in("RESULT", Arrays.asList(InvDtlResultEnum.PROFIT.code, InvDtlResultEnum.NEW_PROFIT.code));
                    addQuery.eq("INV_COUNT_DIF_ID", dif.getInvCountDifId());
                    List<InvCountDifGoods> addDifGoodsList = invCountDifGoodsMapper.selectList(addQuery);
                    QueryWrapper<InvCountDifGoods> subsQurey = new QueryWrapper<>();
                    subsQurey.eq("RESULT", InvDtlResultEnum.LOSS.code);
                    subsQurey.eq("INV_COUNT_DIF_ID", dif.getInvCountDifId());
                    List<InvCountDifGoods> subDifGoodsList = invCountDifGoodsMapper.selectList(subsQurey);

                    //生成入库单
                    if (addDifGoodsList != null && addDifGoodsList.size() > 0) {
                        for (InvCountDifGoods difGoods : addDifGoodsList) {
                            if (difGoods.getReCountQty() == null) {
                                difGoods.setReCountQty(difGoods.getCountQty());
                            }
                        }

                        if (asnHeader == null) {
                            //生成入库单头
                            asnHeader = new AsnHeader();
                            asnHeader.setAsnNo(basicSimpleCodeRuleApi.GenerateCode(R50));
                            asnHeader.setAsnType(AsnTypeEnum.R50.code);
                            asnHeader.setPriority(0);
                            asnHeader.setOwner(ownerId);
                            asnHeader.setAsnCreateTime(nowDate);
                            asnHeader.setToWhs(header.getWhsId());
                            asnHeader.setReleaseStatus(0);
                            asnHeader.setQcStatus(QcStatusEnum.全部质检.getCode());
                            asnHeader.setStatus(AsnHeaderStatusEnum.FINISH.code);
                            asnHeader.setCreateUser(loginName);
                            asnHeader.setCreateTime(nowDate);
                            asnHeader.setDataSource(header.getInvCountNo());
                            asnHeader.setSourceNo(header.getInvCountNo());
                            asnHeaderMapper.insert(asnHeader);
                        }
                        BigDecimal reCountQtys = addDifGoodsList.stream().map(InvCountDifGoods::getReCountQty).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal acCountQtys = addDifGoodsList.stream().map(InvCountDifGoods::getAccountQty).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal orderQty = reCountQtys.subtract(acCountQtys);
                        AsnDtl asnDtl = new AsnDtl();
                        asnDtl.setAsnHeaderId(asnHeader.getAsnHeaderId());
                        asnDtl.setAsnNo(asnHeader.getAsnNo());
                        asnDtl.setAsnLineNo("" + asnLine++);
                        asnDtl.setPoNo(poNo);
                        asnDtl.setSkuId(dif.getSkuId());
                        asnDtl.setLotno(dif.getLotno());
                        asnDtl.setOrderQty(orderQty);
                        asnDtl.setOrderQtyEa(orderQty);
                        asnDtl.setRcvQty(orderQty);
                        asnDtl.setRcvQtyEa(orderQty);
                        asnDtl.setUnit(dif.getUnit());
                        asnDtl.setRcvTime(nowDate);
                        asnDtl.setRcvLocId(dif.getLocId());
                        asnDtl.setInvAttr(dif.getInvAttr());
                        asnDtl.setWhsId(header.getWhsId());
                        asnDtl.setQcStatus(asnHeader.getQcStatus());
                        asnDtl.setCreateTime(nowDate);
                        asnDtl.setCreateUser(loginName);
                        asnDtl.setStatus(AsnDtlStatusEnum.FINISH.code);
                        asnDtlMapper.insert(asnDtl);
                        TrsnHeader trsnHeader = new TrsnHeader();
                        trsnHeader.setNoteNo(basicSimpleCodeRuleApi.GenerateCode(TRSN_ORDER));
                        trsnHeader.setNoteType(TrsnNoteTypeEnum.IN_STORAGE.getCode());
                        trsnHeader.setOwner(header.getOwner());
                        trsnHeader.setFactory(dif.getFactory());
                        trsnHeader.setWhsId(header.getWhsId());
                        trsnHeader.setVendorId(dif.getVendor());
                        trsnHeader.setFmDoc(header.getInvCountNo());
                        trsnHeader.setCreateUser(loginName);
                        trsnHeader.setStatus(TrsnHeaderStatusEnum.CMP.code);
                        trsnHeader.setCreateTime(nowDate);
                        trsnHeaderMapper.insert(trsnHeader);
                        TrsnDtl trsnDtl = new TrsnDtl();
                        trsnDtl.setTrsnHeaderId(trsnHeader.getTrsnHeaderId());
                        trsnDtl.setNoteNo(trsnHeader.getNoteNo());
                        trsnDtl.setNoteLineNo("1");
                        trsnDtl.setFmDoc(header.getInvCountNo());
                        trsnDtl.setInvUpdateFlag(TrsnDtlInvUpdateFlagEnum.IN.code);
                        trsnDtl.setSkuId(dif.getSkuId());
                        trsnDtl.setQty(orderQty);
                        trsnDtl.setUnit(dif.getUnit());
                        trsnDtl.setInvAttr(dif.getInvAttr());
                        trsnDtl.setQaStatus(dif.getQaStatus());
                        trsnDtl.setStatus(TrsnDtlStatusEnum.CMP.code);
                        trsnDtl.setLotno(dif.getLotno());
                        trsnDtl.setCreateUser(loginName);
                        trsnDtl.setCreateTime(nowDate);
                        trsnDtlMapper.insert(trsnDtl);
                        for (InvCountDifGoods difGoods : addDifGoodsList) {

                            AsnDtlGoods asnDtlGoods = new AsnDtlGoods();
                            asnDtlGoods.setGoodsSn(difGoods.getGoodsSn());
                            asnDtlGoods.setAsnDtlId(asnDtl.getAsnDtlId());
                            asnDtlGoods.setGoodsId(Integer.parseInt(difGoods.getGoodsId().toString()));
                            asnDtlGoods.setQaStatus(dif.getQaStatus());
                            asnDtlGoods.setQty(difGoods.getReCountQty().subtract(difGoods.getAccountQty()));
                            asnDtlGoods.setStatus(GdnDtlGoodsStatusEnum.OS_SHIP.code);
                            asnDtlGoods.setCreateUser(loginName);
                            asnDtlGoods.setCreateTime(nowDate);
                            asnDtlGoodsMapper.insert(asnDtlGoods);
                            TrsnDtlGoods trsnDtlGoods = new TrsnDtlGoods();
                            trsnDtlGoods.setGoodsSn(difGoods.getGoodsSn());
                            trsnDtlGoods.setTrsnDtlId(trsnDtl.getTrsnDtlId());
                            trsnDtlGoods.setGoodsId(Integer.parseInt(difGoods.getGoodsId().toString()));
                            trsnDtlGoods.setQaStatus(dif.getQaStatus());
                            trsnDtlGoods.setQty(difGoods.getAccountQty().subtract(difGoods.getReCountQty()));
                            trsnDtlGoods.setStatus(TrsnDtlGoodsStatusEnum.RECEIVED.getCode());
                            trsnDtlGoods.setCreateUser(loginName);
                            trsnDtlGoods.setCreateTime(nowDate);
                            trsnDtlGoodsMapper.insert(trsnDtlGoods);
                        }
                    }

                    //生成出库单
                    if (subDifGoodsList != null && subDifGoodsList.size() > 0) {
                        for (InvCountDifGoods difGoods : subDifGoodsList) {
                            if (difGoods.getReCountQty() == null) {
                                difGoods.setReCountQty(difGoods.getCountQty());
                            }
                        }

                        if (gdnHeader == null) {
                            //生成出库单头
                            gdnHeader = new GdnHeader();
                            String s = basicSimpleCodeRuleApi.GenerateCode(D50);
                            gdnHeader.setGdnNo(s);
                            gdnHeader.setSourceShipNotice(header.getInvCountNo());
                            gdnHeader.setOwner(ownerId);
                            gdnHeader.setShipDate(nowDate);
                            gdnHeader.setDataSource(header.getInvCountNo());
                            gdnHeader.setStatus(GdnHeaderStatusEnum.FINISH.code);
                            gdnHeader.setCreateUser(loginName);
                            gdnHeader.setCreateTime(nowDate);
                            gdnHeaderMapper.insert(gdnHeader);
                        }
                        GdnDtl gdnDtl = new GdnDtl();
                        gdnDtl.setGdnHeaderId(gdnHeader.getGdnHeaderId());
                        gdnDtl.setGdnLineNo(gdnLine++);
                        gdnDtl.setWhsId(header.getWhsId());
                        gdnDtl.setSkuId(dif.getSkuId());
                        gdnDtl.setVendor(dif.getVendor());
                        gdnDtl.setSoNo(soNo);
                        gdnDtl.setSoLineNo(soItem);
                        gdnDtl.setPoNo(poNo);
                        BigDecimal reCountQtys = subDifGoodsList.stream().map(InvCountDifGoods::getReCountQty).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal acCountQtys = subDifGoodsList.stream().map(InvCountDifGoods::getAccountQty).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal orderQty = acCountQtys.subtract(reCountQtys);
                        gdnDtl.setOrderQty(orderQty);
                        gdnDtl.setPickQty(orderQty);
                        gdnDtl.setShipQty(orderQty);
                        gdnDtl.setUnit(dif.getUnit());
                        gdnDtl.setInvAttr(dif.getInvAttr());
                        gdnDtl.setQaStatus(dif.getQaStatus());
                        gdnDtl.setLotno(dif.getLotno());
                        gdnDtl.setStatus(GdnDtlStatusEnum.SHIPMENTED.code);
                        gdnDtl.setCreateTime(nowDate);
                        gdnDtl.setCreateUser(loginName);
                        gdnDtlMapper.insert(gdnDtl);
                        TrsnHeader trsnHeader = new TrsnHeader();
                        trsnHeader.setNoteNo(basicSimpleCodeRuleApi.GenerateCode(TRSN_ORDER));
                        trsnHeader.setNoteType(TrsnNoteTypeEnum.OUT_STORAGE.getCode());
                        trsnHeader.setOwner(header.getOwner());
                        trsnHeader.setFactory(dif.getFactory());
                        trsnHeader.setWhsId(header.getWhsId());
                        trsnHeader.setVendorId(dif.getVendor());
                        trsnHeader.setFmDoc(header.getInvCountNo());
                        trsnHeader.setCreateUser(loginName);
                        trsnHeader.setStatus(TrsnHeaderStatusEnum.CMP.code);
                        trsnHeader.setCreateTime(nowDate);
                        trsnHeaderMapper.insert(trsnHeader);
                        TrsnDtl trsnDtl = new TrsnDtl();
                        trsnDtl.setTrsnHeaderId(trsnHeader.getTrsnHeaderId());
                        trsnDtl.setNoteNo(trsnHeader.getNoteNo());
                        trsnDtl.setNoteLineNo("1");
                        trsnDtl.setFmDoc(header.getInvCountNo());
                        trsnDtl.setInvUpdateFlag(TrsnDtlInvUpdateFlagEnum.OUT.code);
                        trsnDtl.setSkuId(dif.getSkuId());
                        trsnDtl.setQty(orderQty);
                        trsnDtl.setUnit(dif.getUnit());
                        trsnDtl.setInvAttr(dif.getInvAttr());
                        trsnDtl.setQaStatus(dif.getQaStatus());
                        trsnDtl.setStatus(TrsnDtlStatusEnum.CMP.code);
                        trsnDtl.setLotno(dif.getLotno());
                        trsnDtl.setCreateUser(loginName);
                        trsnDtl.setCreateTime(nowDate);
                        trsnDtlMapper.insert(trsnDtl);
                        for (InvCountDifGoods difGoods : subDifGoodsList) {
                            GdnDtlGoods gdnDtlGoods = new GdnDtlGoods();
                            gdnDtlGoods.setGoodsSn(difGoods.getGoodsSn());
                            gdnDtlGoods.setGdnDtlId(gdnDtl.getGdnDtlId());
                            gdnDtlGoods.setGoodsId(Integer.parseInt(difGoods.getGoodsId().toString()));
                            gdnDtlGoods.setQaStatus(dif.getQaStatus());
                            gdnDtlGoods.setQty(difGoods.getAccountQty().subtract(difGoods.getReCountQty()));
                            gdnDtlGoods.setStatus(GdnDtlGoodsStatusEnum.OS_SHIP.code);
                            gdnDtlGoods.setCreateUser(loginName);
                            gdnDtlGoods.setCreateTime(nowDate);
                            gdnDtlGoodsMapper.insert(gdnDtlGoods);
                            TrsnDtlGoods trsnDtlGoods = new TrsnDtlGoods();
                            trsnDtlGoods.setGoodsSn(difGoods.getGoodsSn());
                            trsnDtlGoods.setTrsnDtlId(trsnDtl.getTrsnDtlId());
                            trsnDtlGoods.setGoodsId(Integer.parseInt(difGoods.getGoodsId().toString()));
                            trsnDtlGoods.setQaStatus(dif.getQaStatus());
                            trsnDtlGoods.setQty(difGoods.getAccountQty().subtract(difGoods.getReCountQty()));
                            trsnDtlGoods.setStatus(TrsnDtlGoodsStatusEnum.RECEIVED.getCode());
                            trsnDtlGoods.setCreateUser(loginName);
                            trsnDtlGoods.setCreateTime(nowDate);
                            trsnDtlGoodsMapper.insert(trsnDtlGoods);
                        }
                    }
                }


                //更新盘点差异单调账结果
                if (difList != null && difList.size() > 0) {
                    invCountDifMapper.updateAdjResult(loginName, InvDifAdjResultEnum.SUCCESS.code, difList.stream().map(t -> t.getInvCountDifId()).collect(Collectors.toList()), InvDifStatusEnum.FINISH.code);
                }
            }

            //更新盘点主档
            invCountHeaderMapper.updateHeaderStatus(loginName, InvHeaderStatusEnum.CLOSE.code, hederIds);
//
//        Shift.fatal("//////////////");

            return new Result<>();
        }


    }
